package com.ck.ips.core.aop;

import com.alibaba.fastjson.JSON;
import com.ck.common.model.OperationLog;
import com.ck.common.model.OperationResult;
import com.ck.core.annotation.SysLog;
import com.ck.core.constant.ClientConstant;
import com.ck.core.context.UserContextHolder;
import com.ck.core.util.HttpUtils;
import com.ck.ips.model.vo.UserInfoVO;
import com.ck.ips.service.UserInfoService;
import com.ck.ips.service.sys.OperationLogService;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Arrays;

/**
* @Description: 系统操作日志切面
* @Author: hf
* @Date:    2019/4/19 11:02
* @Version: 1.0
*/
@Aspect
@Component
public class SysOperattionLogAop {
    @Autowired
    private OperationLogService operationLogService;
    @Autowired
    private UserInfoService userInfoService;
    private final static Logger logger = LoggerFactory.getLogger(SysOperattionLogAop.class);
    /**
     *
     * 该切点只会拦截有SysLog注解的方法
     */
    @Pointcut("@annotation(com.ck.core.annotation.SysLog)")
    public void pointcut() {
    }

    /**
     * 记录操作成功日志 （不包含业务校验失败的情况 ，即只要程序没有抛出异常，都会进入该方法）
     * @param point
     * @param returnValue
     */
    @AfterReturning(pointcut="pointcut()", returning="returnValue")
    public void logSuccess(JoinPoint point, Object returnValue) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();

        // 获取注解上的操作模块和内容
        SysLog annotation = method.getAnnotation(SysLog.class);
        String module = annotation.module();
        String content = annotation.content();

        // 操作人ip
        String ip =  HttpUtils.getRemortIP(request);
        // 操作用户名
        String userName = UserContextHolder.currentUser().getUserName();
        // 操作人真实姓名
        String realName = UserContextHolder.currentUser().getRealName();
        // 操作结果
        OperationResult result = (OperationResult) returnValue;
        // 用户信息
        UserInfoVO userInfo = userInfoService.getUserInfo();
        logger.info("@AfterReturning：操作人：" + userName + " ip："+  ip);
        logger.info("@AfterReturning：目标方法：" + point.getSignature().getDeclaringTypeName() + "." + point.getSignature().getName());
        logger.info("@AfterReturning：参数为：" + Arrays.toString(point.getArgs()));
        logger.info("@AfterReturning：返回值为：" + JSON.toJSONString(result));

        // 操作成功的行为，记录操作日志
        if ( ClientConstant.CODE_SUCCESS == result.getCode() ) {
            OperationLog operationLog = new OperationLog();
            operationLog.setUserName(userName);
            operationLog.setRealname(realName);
            operationLog.setOperationTime(System.currentTimeMillis());
            operationLog.setOperationStatus(result.getCode());
            operationLog.setOperationModule(module);
            operationLog.setOperationContent(StringUtils.isNotBlank(content) ? content : (String)result.getMsg());
            operationLog.setOperationIp(ip);
            operationLog.setDepartmentName(userInfo.getDepartmentName());
            operationLog.setRoleName(userInfo.getRoleName());
            operationLogService.saveOperationLog(operationLog);
        }

    }

    /**
     * 记录操作异常日志
     *
     * @param point
     * @param e
     */
    @AfterThrowing(value = "pointcut()", throwing = "e")
    public void logError(JoinPoint point, Exception e) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();

        // 获取注解上的操作模块和内容
        SysLog annotation = method.getAnnotation(SysLog.class);
        String module = annotation.module();

        // 操作人ip
        String ip =  HttpUtils.getRemortIP(request);
        // 操作人
        String userName = UserContextHolder.currentUser().getUserName();
        // 用户信息
        UserInfoVO userInfo = userInfoService.getUserInfo();
        logger.info("@AfterThrowing：操作人：" + userName + " ip："+  ip);
        logger.info("@AfterThrowing：目标方法：" + point.getSignature().getDeclaringTypeName() + "." + point.getSignature().getName());
        logger.info("@AfterThrowing：参数为：" + Arrays.toString(point.getArgs()));
        logger.info("@AfterThrowing：异常类型为：" + e.getMessage());
        OperationLog operationLog = new OperationLog();
        operationLog.setUserName(userName);
        operationLog.setOperationTime(System.currentTimeMillis());
        operationLog.setOperationStatus(ClientConstant.CODE_SYSTEM_ERROR);
        operationLog.setOperationModule(module);
        operationLog.setOperationContent("操作失败，系统程序异常");
        operationLog.setOperationIp(ip);
        operationLog.setDepartmentName(userInfo.getDepartmentName());
        operationLog.setRoleName(userInfo.getRoleName());

        operationLogService.saveOperationLog(operationLog);
    }


}
